/*
 * date: 2009-11-23 
 * author: Maciej Smolenski <jezdnia@gmail.com>
 */
#include <iostream>
#include <netinet/in.h>
#include <boost/program_options.hpp>
#include "config.hpp"
#include "rpc_config.hpp"

namespace po = boost::program_options;
namespace rc = rpc_config;

struct msg_exception{
	std::string m_msg;
	msg_exception(const std::string &p_msg) : m_msg(p_msg) {}
	msg_exception(const char *p_msg) : m_msg(p_msg) {}
};

rc::rpc_config_service<boost::interprocess::open_only_t> config(SHARE_CONFIG_NAME, CONFIG_MUTEX_NAME);

int main(int argc, char *argv[])
{
	
	try
	{
	po::options_description opt_desc("Options");
	opt_desc.add_options()
		("help,h", "produce help message")
		("print,p","print current configuration")
		("add,a", po::value<std::string>(), "add host")
		("del,d", po::value<std::string>(), "delete host")
		("delay", po::value<long>(), "set delay")
		("pg", po::value<int>(), "set process group")
		("pmt", po::value<long>(), "set portmap timeout")
		("pt", po::value<long>(), "set ping timeout")
		;

	po::variables_map vm;
	po::store(po::parse_command_line(argc, argv, opt_desc), vm);
	po::notify(vm);

	if (vm.count("help")>0)
	{
		std::cout << opt_desc << std::endl;
		return 1;
	}

	if (vm.count("print")>0)
	{
		rc::stdset hosts;
		if (config.get_hosts(hosts)==result_failure)
			throw msg_exception("get_hosts failed");
		long delay;
		if (config.get_delay(delay)==result_failure)
			throw msg_exception("get_delay failed");
		long portmap_timeout;
		if (config.get_portmap_timeout(portmap_timeout)==result_failure)
			throw msg_exception("get_portmap_timeout failed");
		long ping_timeout;
		if (config.get_ping_timeout(ping_timeout)==result_failure)
			throw msg_exception("get_ping_timeout failed");
		int pgroup;
		if (config.get_pgroup(pgroup)==result_failure)
			throw msg_exception("get_pgroup failed");

		std::cout << "hosts: " << std::endl;

		for(rc::stdset::const_iterator it=hosts.begin(); it!=hosts.end(); it++)
			std::cout << "\t" << *it << std::endl;

		std::cout << "delay: " << delay << std::endl;

		std::cout << "portmap_timeout: " << portmap_timeout << std::endl;

		std::cout << "ping_timeout: " << ping_timeout << std::endl;

		std::cout << "pgroup: " << pgroup << std::endl;
	}

	if (vm.count("add")>0)
	{
		rc::rpc_host_entry_string he(vm["add"].as<std::string>(), -1, IPPROTO_TCP);
		if (config.add_host(he)==result_failure)
			throw msg_exception("add_host failed");
	}

	if (vm.count("del")>0)
	{
		rc::rpc_host_entry_string he(vm["del"].as<std::string>(), -1, IPPROTO_TCP);
		if (config.del_host(he)==result_failure)
			throw msg_exception("del_host failed");
	}

	if (vm.count("delay")>0)
	{
		long delay = vm["delay"].as<long>();
		if (config.set_delay(delay)==result_failure)
			throw msg_exception("set_delay failed");
	}

	if (vm.count("pg")>0)
	{
		int pgroup = vm["pg"].as<int>();
		if (config.set_pgroup(pgroup)==result_failure)
			throw msg_exception("set_pgroup failed");
	}

	if (vm.count("pmt")>0)
	{
		long portmap_timeout = vm["pmt"].as<long>();
		if (config.set_portmap_timeout(portmap_timeout)==result_failure)
			throw msg_exception("set_portmap_timeout failed");
	}

	if (vm.count("pt"))
	{
		long ping_timeout = vm["pt"].as<long>();
		if (config.set_ping_timeout(ping_timeout)==result_failure)
			throw msg_exception("set_ping_timeout failed");
	}

	}
	catch(std::exception &e) {
		std::cerr << "error: " << e.what() << std::endl;
		return 1;
	}
	catch(msg_exception &e) {
		std::cerr << "error: " << e.m_msg << std::endl;
		return 1;
	}
    	catch(...) {
		std::cerr << "unknown error!" << std::endl;
    	}

	return 0;
}

